home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / jpsrc2.zip / JWRRLE.C < prev    next >
C/C++ Source or Header  |  1991-11-30  |  7KB  |  232 lines

  1. /*
  2.  * jwrrle.c
  3.  *
  4.  * Copyright (C) 1991, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains routines to write output images in RLE format.
  9.  * The Utah Raster Toolkit library is required (version 3.0).
  10.  *
  11.  * These routines may need modification for non-Unix environments or
  12.  * specialized applications.  As they stand, they assume output to
  13.  * an ordinary stdio stream.
  14.  *
  15.  * These routines are invoked via the methods put_pixel_rows, put_color_map,
  16.  * and output_init/term.
  17.  *
  18.  * Based on code contributed by Mike Lijewski.
  19.  */
  20.  
  21. #include "jinclude.h"
  22.  
  23. #ifdef RLE_SUPPORTED
  24.  
  25. /* rle.h is provided by the Utah Raster Toolkit. */
  26.  
  27. #include <rle.h>
  28.  
  29.  
  30. /*
  31.  * output_term assumes that JSAMPLE has the same representation as rle_pixel,
  32.  * to wit, "unsigned char".  Hence we can't cope with 12- or 16-bit samples.
  33.  */
  34.  
  35. #ifndef EIGHT_BIT_SAMPLES
  36.   Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
  37. #endif
  38.  
  39.  
  40. /*
  41.  * Since RLE stores scanlines bottom-to-top, we have to invert the image
  42.  * from JPEG's top-to-bottom order.  To do this, we save the outgoing data
  43.  * in virtual array(s) during put_pixel_row calls, then actually emit the
  44.  * RLE file during output_term.  We use one virtual array if the output is
  45.  * grayscale or colormapped, more if it is full color.
  46.  */
  47.  
  48. #define MAX_CHANS    4    /* allow up to four color components */
  49. static big_sarray_ptr channels[MAX_CHANS]; /* Virtual arrays for saved data */
  50.  
  51. static long cur_output_row;    /* next row# to write to virtual array(s) */
  52.  
  53.  
  54. /*
  55.  * For now, if we emit an RLE color map then it is always 256 entries long,
  56.  * though not all of the entries need be used.
  57.  */
  58.  
  59. #define CMAPBITS    8
  60. #define CMAPLENGTH    (1<<(CMAPBITS))
  61.  
  62. static rle_map *output_colormap; /* RLE-style color map, or NULL if none */
  63. static int number_colors;    /* Number of colors actually used */
  64.  
  65.  
  66. /*
  67.  * Write the file header.
  68.  *
  69.  * In this module it's easier to wait till output_term to actually write
  70.  * anything; here we just request the big arrays we'll need.
  71.  */
  72.  
  73. METHODDEF void
  74. output_init (decompress_info_ptr cinfo)
  75. {
  76.   short ci;
  77.   
  78.   if (cinfo->final_out_comps > MAX_CHANS)
  79.     ERREXIT1(cinfo->emethods, "Cannot handle %d output channels for RLE",
  80.          cinfo->final_out_comps);
  81.   
  82.   for (ci = 0; ci < cinfo->final_out_comps; ci++) {
  83.     channels[ci] = (*cinfo->emethods->request_big_sarray)
  84.             (cinfo->image_width, cinfo->image_height, 1L);
  85.   }
  86.   
  87.   output_colormap = NULL;    /* No output colormap as yet */
  88.   number_colors = 0;
  89.   cur_output_row = 0;        /* Start filling virtual arrays at row 0 */
  90. }
  91.  
  92.  
  93. /*
  94.  * Write some pixel data.
  95.  *
  96.  * This routine just saves the data away in virtual arrays.
  97.  */
  98.  
  99. METHODDEF void
  100. put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
  101.         JSAMPIMAGE pixel_data)
  102. {
  103.   JSAMPROW outputrow[1];    /* a pseudo JSAMPARRAY structure */
  104.   int row;
  105.   short ci;
  106.   
  107.   for (row = 0; row < num_rows; row++) {
  108.     for (ci = 0; ci < cinfo->final_out_comps; ci++) {
  109.       outputrow[0] = *((*cinfo->emethods->access_big_sarray)
  110.             (channels[ci], cur_output_row, TRUE));
  111.       jcopy_sample_rows(pixel_data[ci], row, outputrow, 0,
  112.             1, cinfo->image_width);
  113.     }
  114.     cur_output_row++;
  115.   }
  116. }
  117.  
  118.  
  119. /*
  120.  * Write the color map.
  121.  *
  122.  *  For RLE output we just save the colormap for the output stage.
  123.  */
  124.  
  125. METHODDEF void
  126. put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
  127. {
  128.   size_t cmapsize;
  129.   short ci;
  130.   int i;
  131.  
  132.   if (num_colors > CMAPLENGTH)
  133.     ERREXIT1(cinfo->emethods, "Cannot handle %d colormap entries for RLE",
  134.          num_colors);
  135.  
  136.   /* Allocate storage for RLE-style cmap, zero any extra entries */
  137.   cmapsize = cinfo->color_out_comps * CMAPLENGTH * SIZEOF(rle_map);
  138.   output_colormap = (rle_map *) (*cinfo->emethods->alloc_small) (cmapsize);
  139.   MEMZERO((void *) output_colormap, cmapsize);
  140.  
  141.   /* Save away data in RLE format --- note 8-bit left shift! */
  142.   /* Shifting would need adjustment for JSAMPLEs wider than 8 bits. */
  143.   for (ci = 0; ci < cinfo->color_out_comps; ci++) {
  144.     for (i = 0; i < num_colors; i++) {
  145.       output_colormap[ci * CMAPLENGTH + i] = GETJSAMPLE(colormap[ci][i]) << 8;
  146.     }
  147.   }
  148.   number_colors = num_colors;
  149. }
  150.  
  151.  
  152. /*
  153.  * Finish up at the end of the file.
  154.  *
  155.  * Here is where we really output the RLE file.
  156.  */
  157.  
  158. METHODDEF void
  159. output_term (decompress_info_ptr cinfo)
  160. {
  161.   rle_hdr header;        /* Output file information */
  162.   rle_pixel *output_rows[MAX_CHANS];
  163.   char cmapcomment[80];
  164.   short ci;
  165.   long row;
  166.  
  167.   /* Initialize the header info */
  168.   MEMZERO((void *) &header, SIZEOF(rle_hdr)); /* make sure all bits are 0 */
  169.   header.rle_file = cinfo->output_file;
  170.   header.xmin     = 0;
  171.   header.xmax     = cinfo->image_width  - 1;
  172.   header.ymin     = 0;
  173.   header.ymax     = cinfo->image_height - 1;
  174.   header.alpha    = 0;
  175.   header.ncolors  = cinfo->final_out_comps;
  176.   for (ci = 0; ci < cinfo->final_out_comps; ci++) {
  177.     RLE_SET_BIT(header, ci);
  178.   }
  179.   if (number_colors > 0) {
  180.     header.ncmap   = cinfo->color_out_comps;
  181.     header.cmaplen = CMAPBITS;
  182.     header.cmap    = output_colormap;
  183.     /* Add a comment to the output image with the true colormap length. */
  184.     sprintf(cmapcomment, "color_map_length=%d", number_colors);
  185.     rle_putcom(cmapcomment, &header);
  186.   }
  187.   /* Emit the RLE header and color map (if any) */
  188.   rle_put_setup(&header);
  189.  
  190.   /* Now output the RLE data from our virtual array(s).
  191.    * We assume here that (a) rle_pixel is represented the same as JSAMPLE,
  192.    * and (b) we are not on a machine where FAR pointers differ from regular.
  193.    */
  194.   for (row = cinfo->image_height-1; row >= 0; row--) {
  195.     for (ci = 0; ci < cinfo->final_out_comps; ci++) {
  196.       output_rows[ci] = (rle_pixel *) *((*cinfo->emethods->access_big_sarray)
  197.                     (channels[ci], row, FALSE));
  198.     }
  199.     rle_putrow(output_rows, (int) cinfo->image_width, &header);
  200.   }
  201.  
  202.   /* Emit file trailer */
  203.   rle_puteof(&header);
  204.   fflush(cinfo->output_file);
  205.   if (ferror(cinfo->output_file))
  206.     ERREXIT(cinfo->emethods, "Output file write error");
  207.  
  208.   /* Release memory */
  209.   for (ci = 0; ci < cinfo->final_out_comps; ci++) {
  210.     (*cinfo->emethods->free_big_sarray) (channels[ci]);
  211.   }
  212.   if (output_colormap != NULL)
  213.     (*cinfo->emethods->free_small) ((void *) output_colormap);
  214. }
  215.  
  216.  
  217. /*
  218.  * The method selection routine for RLE format output.
  219.  * This should be called from d_ui_method_selection if RLE output is wanted.
  220.  */
  221.  
  222. GLOBAL void
  223. jselwrle (decompress_info_ptr cinfo)
  224. {
  225.   cinfo->methods->output_init    = output_init;
  226.   cinfo->methods->put_color_map  = put_color_map;
  227.   cinfo->methods->put_pixel_rows = put_pixel_rows;
  228.   cinfo->methods->output_term    = output_term;
  229. }
  230.  
  231. #endif /* RLE_SUPPORTED */
  232.